package com.ruoyi.framework.config;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.api.impl.WxMaServiceImpl;
import cn.binarywang.wx.miniapp.config.impl.WxMaDefaultConfigImpl;
import com.ruoyi.common.constant.Constants;
import com.wechat.pay.contrib.apache.httpclient.WechatPayHttpClientBuilder;
import com.wechat.pay.contrib.apache.httpclient.auth.PrivateKeySigner;
import com.wechat.pay.contrib.apache.httpclient.auth.Verifier;
import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Credentials;
import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Validator;
import com.wechat.pay.contrib.apache.httpclient.cert.CertificatesManager;
import com.wechat.pay.contrib.apache.httpclient.util.PemUtil;
import com.wechat.pay.java.core.RSAAutoCertificateConfig;
import com.wechat.pay.java.core.cipher.PrivacyEncryptor;
import com.wechat.pay.java.core.http.DefaultHttpClientBuilder;
import com.wechat.pay.java.core.http.HttpClient;
import okhttp3.OkHttpClient;
import org.apache.http.impl.client.CloseableHttpClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.security.PrivateKey;

/*
@description:
@ClassName DefaultConfig
@author chen
@create 2025-03-13 11:16
@Version 1.0
*/
@Configuration
public class DefaultConfig
{

    @Bean("encryptor")
    public PrivacyEncryptor encryptor()
    {
        RSAAutoCertificateConfig rsaAutoCertificateConfig = new RSAAutoCertificateConfig.Builder()
                // 商户号
                .merchantId(Constants.APPLET_MCH_ID)
                // 商户API证书私钥
                .privateKey(getPrivateKey())
                // 商户API证书序列号
                .merchantSerialNumber(Constants.MCH_SERIAL_NO)
                // APIv3密钥
                .apiV3Key(Constants.API_V3KEY)
                .build();
        return rsaAutoCertificateConfig.createEncryptor();
    }




    @Bean("transferHttpClient")
    public HttpClient getHttpClient()
    {

        OkHttpClient okHttpClient = new OkHttpClient();

        RSAAutoCertificateConfig rsaAutoCertificateConfig = new RSAAutoCertificateConfig.Builder()
                // 商户号
                .merchantId(Constants.APPLET_MCH_ID)
                // 商户API证书私钥
                .privateKey(getPrivateKey())
                // 商户API证书序列号
                .merchantSerialNumber(Constants.MCH_SERIAL_NO)
                // APIv3密钥
                .apiV3Key(Constants.API_V3KEY)
                .build();

        return new DefaultHttpClientBuilder()
                .config(rsaAutoCertificateConfig)
                .okHttpClient(okHttpClient)
                .build();
    }


    @Bean(name = "wxPayNoSignClient")
    public CloseableHttpClient getWxPayNoSignClient(Verifier verifier)
    {
        PrivateKey privateKey = getPrivateKey();
        //用于构造HttpClient
        WechatPayHttpClientBuilder builder = WechatPayHttpClientBuilder.create()
                .withMerchant(Constants.APPLET_MCH_ID, Constants.MCH_SERIAL_NO, privateKey)
                .withValidator(new WechatPay2Validator(verifier))
                .withValidator((response) -> true);
        return builder.build();
    }


    @Bean
    public Verifier getVerifier() throws Exception
    {
        //获取商户私钥
        PrivateKey privateKey = getPrivateKey();
        // 私钥签名对象
        PrivateKeySigner keySigner = new PrivateKeySigner(Constants.MCH_SERIAL_NO, privateKey);
        // 身份认证对象
        WechatPay2Credentials wechatPay2Credentials = new WechatPay2Credentials(Constants.APPLET_MCH_ID, keySigner);

        // 获取证书管理器实例
        CertificatesManager certificatesManager = CertificatesManager.getInstance();
        // 向证书管理器增加需要自动更新平台证书的商户信息
        certificatesManager.putMerchant(Constants.APPLET_MCH_ID, wechatPay2Credentials,
                Constants.API_V3KEY.getBytes(StandardCharsets.UTF_8));
        // ... 若有多个商户号，可继续调用putMerchant添加商户信息
        return  certificatesManager.getVerifier(Constants.APPLET_MCH_ID);
    }



    @Bean
    public PasswordEncoder passwordEncoder()
    {
        // 配置密码加密，这里声明成bean，方便注册用户时直接注入
        return new BCryptPasswordEncoder();
    }

    @Bean
    public WxMaService wxMaService()
    {
        WxMaDefaultConfigImpl config = new WxMaDefaultConfigImpl();
        config.setAppid(Constants.APPLET_APPID);
        config.setSecret(Constants.APPLET_SECRET);
        WxMaService service = new WxMaServiceImpl();
        service.setWxMaConfig(config);
        return service;
    }


    private PrivateKey getPrivateKey()
    {
        InputStream inputStream = DefaultConfig.class.getClassLoader().getResourceAsStream("client/apiclient_key.pem");
        assert inputStream != null;
        return PemUtil.loadPrivateKey(inputStream);
    }
}
